-- Natur EnemyCastBar PvP Module LUA

function NECB_OnEvent_PvP_SC(event)

	--BC detects casts out of combat range and adjusts casttime duration, even detects and displays unknown spells now!
 	--Events deregistered if PvP disabled or Onlygains enabled
	if (event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_CHANNEL_START") then

		NECB_SpellStart(arg1); -- outsourced since used by TargetChanged function (6.6.x)

	--BC add this to detect casttime delays
	elseif (event == "UNIT_SPELLCAST_DELAYED" or event == "UNIT_SPELLCAST_CHANNEL_UPDATE") then
		if (((arg1 == "target" and not CEnemyCastBar.bFocusPvPOnly) or (arg1 == "focus" and CEnemyCastBar.bFocusPvP)) and not UnitIsUnit(arg1, "player") ) then
			local UCI_spell, UCI_startTime, UCI_endTime;
			if (event == "UNIT_SPELLCAST_DELAYED") then
				UCI_spell, _, _, _, UCI_startTime, UCI_endTime = UnitCastingInfo(arg1);
			else
				UCI_spell, _, _, _, UCI_startTime, UCI_endTime = UnitChannelInfo(arg1);
			end
			if (not UCI_spell or (CEnemyCastBar_PvECheck((UnitName(arg1)), UCI_spell, bcasted, event) and CEnemyCastBar_Raids[UCI_spell].c ~= "hostile") ) then
				return;	-- do not overwrite PvE cooldowns with same same; they will be called globally anyway!
			end
			CEnemyCastBar_UniqueCheck(UCI_spell, UCI_startTime/1000, (UnitName(arg1)), "trueupdate", "delay", UCI_endTime/1000,"casts");
			--DEFAULT_CHAT_FRAME:AddMessage("Time: "..GetTime().." - Start: "..UCI_startTime.." - End: "..UCI_endTime);
			--BC changes made to unique function to support this
		end

	elseif (event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_CHANNEL_STOP") then
		if (((arg1 == "target" and not CEnemyCastBar.bFocusPvPOnly) or (arg1 == "focus" and CEnemyCastBar.bFocusPvP)) and not UnitIsUnit(arg1, "player") and not (CEnemyCastBar_PvECheck((UnitName(arg1)), UCI_spell, bcasted, event) and CEnemyCastBar_Raids[UCI_spell].c ~= "hostile") ) then
			CEnemyCastBar_Control_interrupt((UnitName(arg1)) );
		end

	-- put large check at the end, because it will generate lots of CPU/Mem hits anyway and might often get disabled for better performance
	elseif (event == "CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE"
		or event == "CHAT_MSG_SPELL_FRIENDLYPLAYER_DAMAGE"
		or event == "CHAT_MSG_SPELL_PARTY_DAMAGE"

		or event == "CHAT_MSG_SPELL_FRIENDLYPLAYER_BUFF"
		or event == "CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF"

		or event == "CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE"
		or event == "CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF"

		or event == "CHAT_MSG_SPELL_CREATURE_VS_PARTY_DAMAGE" -- naxx only :/
		or event == "CHAT_MSG_SPELL_CREATURE_VS_SELF_DAMAGE" -- naxx only :/

		or event == "CHAT_MSG_SPELL_PARTY_BUFF" -- does not fire atm, instead HOSTILEPLAYER_BUFF is called
	) then

		CEnemyCastBar_Gfind_PvP(arg1, event);
			-- Big Parser!
			-- what a nice distribution at all now! :D

	end
end


function NECB_PvP_Control(mob, spell, special, bcasted, event, rank, stack)

	if (CEnemyCastBar.bPvP) then

		--BC casttime and spell adjustment; won't show multiple bars if mobs with same name cast!
		if ( ((special == "casts" or special == "performs") and ((UnitName("target") == mob and not CEnemyCastBar.bFocusPvPOnly) or (UnitName("focus") == mob and CEnemyCastBar.bFocusPvP)) and event ~= "UNIT_SPELLCAST_START" and event ~= "UNIT_SPELLCAST_CHANNEL_START") --  'and PvECheckPassed' removed; currently see no need+bug; (before:)don't use ctype check here, otherwise PvE cooldowns might be blocked by PvP spells!
			or (special == "instcast" and (not CEnemyCastBar_Spells[spell] or not CEnemyCastBar_Spells[spell].icasted))
			) then
			return; -- because SPELLCAST_START will catch it!
				-- and instcast barrier
		end

		-- initialize locals, since this a separated mod now

		-- initialize vars
		local ctype, castime;

		-- check if spell stacks (careful: casts like Healthstone (greater etc.) must be rebuilt)
		-- gains: (Livebloom (3) ) stack
		-- now uses strings, too, but won't be cleared on fades! -- obsolete since 8 3 0
		-- check if spell stacks (number)
		if (stack and not string.match(stack, "%((%d+)%)") ) then
			stack = nil;
		end

		-- crop the german aposthrophes from some spells (') -- obsolete since patterns are generated from globalstrings


		-- CD Buffer Routine
		if (CEnemyCastBar.bCDown
			and CEnemyCastBar_Spells[spell]
			and CEnemyCastBar_Spells[spell].d
			and not (UnitName("target") == mob and not UnitIsPlayer("target"))
			and not (UnitName("focus") == mob and not UnitIsPlayer("focus"))
			and not (CEnemyCastBar_Spells[spell].g == 0 and special == "gains")
		) then

			if (special == "casts" or special == "gains" or special == "performs" or special == "instcast") then

				castime = CEnemyCastBar_Spells[spell].d;

				if (special == "casts" and CEnemyCastBar_Spells[spell].t and not CEnemyCastBar_Spells[spell].channeled) then
					castime = castime + CEnemyCastBar_Spells[spell].t;
				end

				local i = 1;
				local CDDBUpdated = false;
				-- add CD to database
				while i <= #NECB_CD_DB do
					if ( NECB_CD_DB[i][1] == mob and NECB_CD_DB[i][2] == spell ) then
						NECB_CD_DB[i][3] = GetTime();
						CDDBUpdated = true;
					elseif ( GetTime() > ( NECB_CD_DB[i][3] + NECB_CD_DB[i][4] ) ) then
						table.remove(NECB_CD_DB, i);
						i = i - 1;
					end
					i = i + 1;
				end

				if ( not CDDBUpdated and mob ~= UnitName("player") and not CEnemyCastBar_Spells[spell].disabled and #NECB_CD_DB < 50) then
					table.insert(NECB_CD_DB, { mob, spell, GetTime(), castime } );
					--DEFAULT_CHAT_FRAME:AddMessage("Mob: "..mob.." |Spell: "..spell);
				end
			end
		end
		-- CD Buffer Routine finished

		local hostilemob;
		if (CEnemyCastBar.bGlobalPvP) then
			hostilemob = CEnemyCastBar_IsHostile(event,mob);
		end

		if (	(   (UnitName("target") == mob and not CEnemyCastBar.bFocusPvPOnly)
			 or (UnitName("focus") == mob and CEnemyCastBar.bFocusPvP)
			 or (CEnemyCastBar.bGlobalPvP and (not CEnemyCastBar.bHostileOnly or hostilemob))
			)
			 and mob ~= UnitName("player")
		) then

			if (special == "instcast") then
				special = "gains"; --rename to make things easier ('summon water elemental'); to display cd and to color bar if 't'
			end

		    if (special == "casts" or special == "gains" or special == "performs") then

			if (CEnemyCastBar_Spells[spell]) then


				if (	-- filter:
						-- check if previously disabled with shift + leftclick
					CEnemyCastBar_Spells[spell].disabled
						-- check if only gains are allowed
					or (CEnemyCastBar.bGainsOnly and CEnemyCastBar.bGains and special ~= "gains")
					or (CEnemyCastBar.bHealFilter and special == "gains" and not (CEnemyCastBar_Spells[spell].HoT or CEnemyCastBar_Spells[spell].cgain) )
					or (CEnemyCastBar.bHealCastOnly and special == "casts" and not CEnemyCastBar_Spells[spell].heal)
					) then
					return;
				end

				local icontex = CEnemyCastBar_Spells[spell].icontex; -- > get icon texture
				local alreadyshowing = 0;

				-- new with NECB 6.9.x, to update focus bars
				local necb_unit = "target";
				if (UnitName("focus") == mob) then
					necb_unit = "focus";
				end

				if (special ~= "gains") then
					if (mob == UnitName(necb_unit)) then
						if (UnitIsEnemy("player", necb_unit) ) then
							ctype = "hostile";
						else
							ctype = "friendly";
						end
	
					else
						if (hostilemob == nil) then
							hostilemob = CEnemyCastBar_IsHostile(event,mob);
						end
						if (hostilemob) then
							ctype = "hostile";
						else
							ctype = "friendly";
						end
	
					end
				end


				if (CEnemyCastBar_Spells[spell].i) then
				
					castime = CEnemyCastBar_Spells[spell].i;
					CEnemyCastBar_Show(mob, spell, castime, ctype, nil, icontex);					
				
				end
				
				if (CEnemyCastBar_Spells[spell].d and CEnemyCastBar.bCDown and UnitName(necb_unit) == mob and UnitIsPlayer(necb_unit) ) then

					if (special == "gains" and CEnemyCastBar.bGains and not (CEnemyCastBar_Spells[spell].g == 0)) then
						local _, targetsclass = UnitClass(necb_unit);
						castime = CEnemyCastBar_Spells[spell].d;
						if (not (CEnemyCastBar_Spells[spell].cdclass and CEnemyCastBar_Spells[spell].cdclass ~= targetsclass) and CEnemyCastBar_UniqueCheck(spell.." (CD)", castime, mob, "trueupdate", nil, nil,"cooldown") == 0) then
							CEnemyCastBar_Show(mob, spell.." (CD)", castime, "cooldown", nil, icontex);
						end
					end
				end


				if (event == "UNIT_SPELLCAST_START") then
					castime = bcasted;
					bcasted = false;
				elseif (event == "UNIT_SPELLCAST_CHANNEL_START") then
					castime = bcasted;
					bcasted = true; --tell 'show' that a channeling spell comes
				else
					castime = CEnemyCastBar_Spells[spell].t; -- but if only "d=" is applied then "t=nil", so check at end of this block
					bcasted = false;
				end
				
				-- Spell might have the same name but a different cast time on another mob, ie. Death Talon Hatchers/Players on Bellowing Roar
				if (CEnemyCastBar_Spells[spell].r) then
				
					if (mob == CEnemyCastBar_Spells[spell].r) then
					
						castime = CEnemyCastBar_Spells[spell].a;
					
					end
				
				end

				if (special == "gains") then

					if (CEnemyCastBar.bGains) then

						if (event and (string.match(event, "HOSTILE") or string.match(event, "CREATURE") ) and not (UnitName(necb_unit) == mob and not UnitIsEnemy("player", necb_unit)) ) then
							ctype = "gainsfoe";
						else
							ctype = "gainsfriend";
						end
						if (CEnemyCastBar_Spells[spell].g) then
						
							castime = CEnemyCastBar_Spells[spell].g;
						
						end
						if (CEnemyCastBar_Spells[spell].HoT) then
							alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,"trueupdate","HoT", nil, "allgains");
						else
							alreadyshowing = CEnemyCastBar_UniqueCheck(spell,castime,mob,"trueupdate",stack, nil,"allgains");
						end
						
					else

						return;

					end

				end

				if (CEnemyCastBar_Spells[spell].c) then
				
					ctype = CEnemyCastBar_Spells[spell].c;
				
				end

				-- rebuild original spellname for casts with bracket (fearie fire in bearform etc.) -- old, 8 3 0+

				-- display spell rank for real PvP (hostile + friendly) -- old, changed 8 3 0+
				if (rank) then
					stack = rank; -- simple override, changed with 8 3 0
				end

				if (castime and castime ~= 0 and not (special == "gains" and alreadyshowing == 1) ) then
					CEnemyCastBar_Show(mob, spell, castime, ctype, nil, icontex, nil, stack, nil, bcasted); -- bcasted = channeling or not

					--play sound warning
					if (CEnemyCastBar.bPvPSoundWarn and CEnemyCastBar_Spells[spell].swarn and mob == UnitName(necb_unit) and UnitIsPlayer(necb_unit) and UnitIsEnemy("player", necb_unit) ) then

						if (CEnemyCastBar.bScreamWarn) then
							PlaySoundFile("Interface\\AddOns\\CEnemyCastBar\\Sounds\\scream.wav");
						else
							PlaySoundFile("Sound\\Spells\\Thorns.wav");
						end
					end
				end

		 	end
		
		    end

		end
			
	end

end


function CEnemyCastBar_IsHostile(event, mob) --ishostile?

	if (event == "CHAT_MSG_SPELL_HOSTILEPLAYER_DAMAGE" or event == "CHAT_MSG_SPELL_CREATURE_VS_CREATURE_DAMAGE"
		or event == "CHAT_MSG_SPELL_HOSTILEPLAYER_BUFF" or event == "CHAT_MSG_SPELL_PERIODIC_HOSTILEPLAYER_BUFFS"
		or event == "CHAT_MSG_SPELL_CREATURE_VS_CREATURE_BUFF" or event == "CHAT_MSG_SPELL_PERIODIC_CREATURE_BUFFS"
		) then

		local status = true;

		local number, unittype = 0;
		if (GetNumRaidMembers() ~= 0) then
			number = GetNumRaidMembers();
			unittype = "raid";
		elseif (GetNumPartyMembers() ~= 0) then
			number = GetNumPartyMembers();
			unittype = "party";
		end

		for i = 1, number do
			if ( (UnitName(unittype .. i) == mob and not UnitIsEnemy("player", unittype .. i) )
				or (UnitName(unittype.."pet".. i) == mob and not UnitIsEnemy("player", unittype.."pet".. i))
			) then
				status = false;
			end
		end

		return status;

	else
		return false;
	end
end

function NECB_BuffLauncher()
	if (GetTime() - NECB_Buff_timer > 1) then
		NECB_BuffFauxTimer:Hide();
		NECBGatherBuffs();
	end
end

local NECB_gatherbuff_unit = {"focus", "target"};
function NECBGatherBuffs()

	if (UnitExists("target") or UnitExists("focus") ) then

		local name, count, duration, timeLeft;
		local gounits = 2;

		if (CEnemyCastBar.bFocusDebuffs and UnitExists("focus")) then
			gounits = 1;
		end -- update focus first, otherwise normal debuffs of target will be overridden by focus unit's name! Might produce strange bar behavior in some cases...
	
		for u=gounits, 2 do
	
			local i = 1;
			while UnitBuff(NECB_gatherbuff_unit[u], i) do
				name, _, _, count, duration, timeLeft = UnitBuff(NECB_gatherbuff_unit[u], i);

				if (timeLeft) then

					if ( CEnemyCastBar_Spells[name]
						and (CEnemyCastBar_Spells[name].HoT or CEnemyCastBar_Spells[name].nofade) -- nofade = Lifebloom try out
						and count == 0
					) then

						local minbar, maxbar = 1, CEnemyCastBar.bNumBars;
						if (CEnemyCastBar.bSeparateBars) then
							minbar, maxbar = 3 * CEnemyCastBar.bNumBarsSep + 1, 4 * CEnemyCastBar.bNumBarsSep; -- friendly gains
						end

						for i=minbar, maxbar do
							local bar = getglobal("Carni_ECB_"..i);

							if (bar.spell == name) then

								-- this looks best, although it does not modifiy anything out of the gained data (timeLeft)
								bar.activeHoTEnd = bar.endTime;
									--DEFAULT_CHAT_FRAME:AddMessage("shortened by "..bar.endTime - bar.activeHoTEnd)--
									--/6 Offizier Maloof bekommt Erneuerung.
								bar.activeHoTStart = bar.startTime; -- not needed to clear in hide func, not queried
								getglobal("Carni_ECB_"..i.."_StatusBar_SparkHoT"):Show();
							end
						end
					end
				else
					break;
				end
				i=i+1;
			end
		end
	end
end












NECB_PvP_Module_loaded = true;
--NECB_InfoFrame:AddMessage("|cffaaaaaaNECB:|r PvP Module loaded into memory!", 1, 0.5, 0, 1, UIERRORS_HOLD_TIME);